﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DungeonDelver.Common
{
    public class CountedCollection<T>:ICountedCollection<T>
    {
        private Dictionary<T, uint> theCounts = new Dictionary<T, uint>();
        private const uint One = 1;

        public void Add(T theKey)
        {
            Add(theKey, One);
        }

        public void Add(T theKey, uint theCount)
        {
            if (theCount > uint.MinValue)
            {
                if (Has(theKey))
                {
                    if (uint.MaxValue - this[theKey] < theCount)
                    {
                        throw new OverflowException();
                    }
                    else
                    {
                        this[theKey] += theCount;
                    }
                }
                else
                {
                    this[theKey] = theCount;
                }
            }
        }

        public void Remove(T theKey)
        {
            Remove(theKey, One);
        }

        public void Remove(T theKey, uint theCount)
        {
            if (theCount > uint.MinValue)
            {
                if (!Has(theKey))
                {
                    throw new OverflowException();
                }
                else
                {
                    if (this[theKey] < theCount)
                    {
                        throw new OverflowException();
                    }
                    else
                    {
                        this[theKey] -= theCount;
                    }
                }
            }
        }

        public bool Has(T theKey)
        {
            return theCounts.ContainsKey(theKey);
        }

        public uint this[T theIndex]
        {
            get
            {
                if (theCounts.ContainsKey(theIndex))
                {
                    return theCounts[theIndex];
                }
                else
                {
                    return uint.MinValue;
                }
            }
            set
            {
                if (value == uint.MinValue)
                {
                    if (theCounts.ContainsKey(theIndex))
                    {
                        theCounts.Remove(theIndex);
                    }
                }
                else
                {
                    if (theCounts.ContainsKey(theIndex))
                    {
                        theCounts[theIndex] = value;
                    }
                    else
                    {
                        theCounts.Add(theIndex, value);
                    }
                }
            }
        }

        public IEnumerable<T> Keys
        {
            get { return theCounts.Keys; }
        }


        public void Clear()
        {
            theCounts.Clear();
        }

        public CountedCollection()
        {
        }

        public CountedCollection(Dictionary<T,uint> theTable)
        {
            Table = theTable;
        }


        public Dictionary<T, uint> Table
        {
            get
            {
                Dictionary<T, uint> result = new Dictionary<T, uint>(theCounts);
                return result;
            }
            set
            {
                if (value == null)
                {
                    Clear();
                }
                else
                {
                    theCounts = new Dictionary<T, uint>(value);
                }
            }
        }
    }
}
